今日事,今日畢。完成鐵人文才算今日畢唷!Go~
github傳送門:https://github.com/uuko/modulepra
安安,在昨天講完基礎DI知識之後,今天來介紹一下Dagger
/*
Q:@Module作用?
提供的地方,主要標記要提供甚麼
標記用的Annoatation 為@Provides是用來標記function之類的
/Singleton 單例模式 在同一個component作用域下只有一個/
/Provides 提供依賴實例/
Q:@Named作用?
A:使用 @Named 標記 Module 中生成class實例的方法
如下面的@Named("UserApiUrl") 就是將他回傳的String命名為UserApiUrl
而當我們Retrofit需要url的時候在參數
Retrofit provideUserRetrofit(@Named("UserApiUrl") String url..
就能找到你提供的地方,讓他可以成功匹配到
創一個APIModule
@Module
public class APIModule {
@Provides
@Singleton
APIService provideUserApi(@Named("UserApi")Retrofit retrofit){
return retrofit.create(APIService.class);
}
@Provides
@Singleton
@Named("UserApi")
Retrofit provideUserRetrofit(@Named("UserApiUrl") String url,
@Named("UserApiClient") OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(url)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
//addCallAdapterFactory 是要支援有Observerable的
}
@Singleton
@Provides
@Named("UserApiUrl")
String provideUserApiUrl(){
return "https://jsonplaceholder.typicode.com";
//如果要getResource要context.get ...
}
@Singleton
@Provides
@Named("UserApiClient")
OkHttpClient provideUserOkhttpClient(HttpLoggingInterceptor httpLoggingInterceptor){
return new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20,TimeUnit.SECONDS)
.writeTimeout(20,TimeUnit.SECONDS)
.build();
}
//HttpLoggingInterceptor 有404 200 等連線狀態用的
@Provides
@Singleton
public HttpLoggingInterceptor provideHttpLoggingInterceptor() {
return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
}
}
APIService貼這邊
public interface APIService {
@GET("/users")
Observable<List<Users>> getUsers();
}
而我們要提供一個主要的(可要可不要),只是我習慣如果有整個Application共用就創一個Module跟一個Component裝進去
在裡面提供Application跟Context上下文,以便要用的時候可以用到
@Module
public class ApplicationModule {
private Application mApplication;
/*從全局 application拿到application*/
public ApplicationModule(Application application){
this.mApplication=application;
}
/*提供整個應用程序的上下文*/
@Provides
public Context provideContext(){
return mApplication.getApplicationContext();
}
/*提供整個應用程序的application*/
@Provides
public Application provideApplication(){
return mApplication;
}
/*提供Composiable 為了給別的Module使用*/
@Provides
public CompositeDisposable provideCompositeDisposable() {
return new CompositeDisposable();
}
}
Q:@Component作用?
A:為interface,在@Component中可以標記要引用那些module
而APIService跟CompositeDisposable都需要提供出去
也因為跟其他的component是依賴關係 所以提供給他們*
@Singleton
@Component(modules = {APIModule.class
,ApplicationModule.class
,SockettModule.class})
public interface ApplicationComponent {
/*depency需求者可以呼叫*/
void inject(Application application);
/*跟其他的component是依賴關係 所以提供給他們*/
APIService getUserApi();
CompositeDisposable getCompositediposable();
/*如果有name的話一定要記得給*/
@Named("APIServiceConnection")
ApiSocketProvider apiSocketProviderConnect();
}
注:如果有Named的話一定要記得給才吃的到他在哪
前面有說到我習慣把如果所有都有提供的綁到Application
所以我們現在來自定義全局變量 Application
然後要綁定的話用
要用前面的inject綁定
DaggerApplicationComponent.builder(內建),在寫這之前要先build一下才能用
applicationComponent=DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.aPIModule(new APIModule())
.sockettModule(new SockettModule())
.build();
applicationComponent.inject(this);
/*自定義全局變量 Application
* 要在manifest加上android:name=""
* */
public class Application extends android.app.Application {
private ApplicationComponent applicationComponent;
public static Application get(Context context)
{
return (Application)context.getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
applicationComponent=DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.aPIModule(new APIModule())
.sockettModule(new SockettModule())
.build();
applicationComponent.inject(this);
}
public ApplicationComponent getApplicationComponent(){
return applicationComponent;
}
}
注:要在manifest加上android:name=""加上自定的Application